home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Networking / ARPSample1.0b1 / ARPSampleShell.c < prev    next >
Encoding:
Text File  |  1997-04-03  |  13.5 KB  |  507 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        ARPSampleShell.c
  3.  
  4.     Contains:    Sample that shows how to talk to the ARP module.
  5.  
  6.     Written by:    Quinn "The Eskimo!"
  7.  
  8.     Copyright:    © 1997 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.     You may incorporate this sample code into your applications without
  13.     restriction, though the sample code has been provided "AS IS" and the
  14.     responsibility for its operation is 100% yours.  However, what you are
  15.     not permitted to do is to redistribute the source as "DSC Sample Code"
  16.     after having made changes. If you're going to re-distribute the source,
  17.     we require that you make it clear in the source that the code was
  18.     descended from Apple Sample Code, but that you've made changes.
  19. */
  20.  
  21. ///////////////////////////////////////////////////////////////////
  22. // Lots of standard OT constructs.
  23.  
  24. #include <OpenTptClient.h>
  25. #include <OpenTptInternet.h>
  26.  
  27. ///////////////////////////////////////////////////////////////////
  28. // This sample makes heavy use of C's standard I/O package.
  29.  
  30. #include <stdio.h>
  31.  
  32. ///////////////////////////////////////////////////////////////////
  33. // Standard C string operations.
  34.  
  35. #include <string.h>
  36.  
  37. ///////////////////////////////////////////////////////////////////
  38. // Constants and types for ARP module messages.
  39.  
  40. #include "OTARPModule.h"
  41.  
  42. ///////////////////////////////////////////////////////////////////
  43. // Prototypes for our high-level interface to ARP.
  44.  
  45. #include "ARPerations.h"
  46.  
  47. ///////////////////////////////////////////////////////////////////
  48.  
  49. // Define a structure for holding a standard hardware address,
  50. // ie a 6 byte Ethernet address.
  51.  
  52. struct HardwareAddress {
  53.     UInt8    fHardwareAddress[6];
  54. };
  55. typedef struct HardwareAddress HardwareAddress;
  56.  
  57. ///////////////////////////////////////////////////////////////////
  58.  
  59. // Define constants for all the default address and such that we
  60. // assume if you enter a blank field.
  61.  
  62. static char             kDefaultInterfaceName[] = "pci1011,140";
  63. static HardwareAddress     kDefaultHardwareAddress = { 0x00, 0x05, 0x02, 0xBC, 0xC8, 0x4F };
  64. static InetHost         kDefaultIPAddress = ( (17L << 24) || (203L << 16) || (21L << 8) || 98);
  65. static char             kDefaultInterfaceConfig[] = "enet";
  66.  
  67. ///////////////////////////////////////////////////////////////////
  68.  
  69. // Routines for reading and writing various address types.
  70.  
  71. static void GetHardwareAddress(HardwareAddress *hwAddr)
  72.     // Prompt the user for a hardware address.
  73. {
  74.     unsigned int hw0, hw1, hw2, hw3, hw4, hw5;
  75.     int result;
  76.     char tmpStr[256];
  77.     
  78.     printf("Enter a hardware address:\n");
  79.     tmpStr[0] = 0;
  80.     gets(tmpStr);
  81.     printf("“%s”\n", tmpStr);
  82.     result = sscanf(tmpStr, "%x:%x:%x:%x:%x:%x", &hw0, &hw1, &hw2, &hw3, &hw4, &hw5);
  83.     
  84.     if (result != 6) {
  85.         printf("Wrong answer. Using default hardware address.\n");
  86.         *hwAddr = kDefaultHardwareAddress;
  87.     } else {
  88.         hwAddr->fHardwareAddress[0] = hw0;
  89.         hwAddr->fHardwareAddress[1] = hw1;
  90.         hwAddr->fHardwareAddress[2] = hw2;
  91.         hwAddr->fHardwareAddress[3] = hw3;
  92.         hwAddr->fHardwareAddress[4] = hw4;
  93.         hwAddr->fHardwareAddress[5] = hw5;
  94.     }
  95. }
  96.  
  97. static void HardwareAddressToString(HardwareAddress hwAddr, char *outputString)
  98.     // Convert a hardware address to a string suitable for printing.
  99. {
  100.     sprintf(outputString, "%02x:%02x:%02x:%02x:%02x:%02x", 
  101.         hwAddr.fHardwareAddress[0],
  102.         hwAddr.fHardwareAddress[1],
  103.         hwAddr.fHardwareAddress[2],
  104.         hwAddr.fHardwareAddress[3],
  105.         hwAddr.fHardwareAddress[4],
  106.         hwAddr.fHardwareAddress[5]
  107.         );
  108. }
  109.  
  110. static void GetInterfaceName(char *intfName)
  111.     // Prompt the user for an interface name.
  112. {
  113.     printf("Enter an ARP interface name (press return for “%s”):\n", kDefaultInterfaceName);
  114.     intfName[0] = 0;
  115.     gets(intfName);
  116.     if (intfName[0] == 0) {
  117.         strcpy(intfName, kDefaultInterfaceName);
  118.     }
  119. }
  120.  
  121. static void GetIPAddress(InetHost *ipAddr)
  122.     // Prompt the user for an IP address.
  123. {
  124.     char tmpStr[256];
  125.     unsigned int ip0, ip1, ip2, ip3;
  126.     int result;
  127.     
  128.     printf("Enter an IP address:\n");
  129.     tmpStr[0] = 0;
  130.     gets(tmpStr);
  131.     result = sscanf(tmpStr, "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);
  132.     
  133.     if (result != 4) {
  134.         printf("Wrong answer. Using default IP address.\n");
  135.         *ipAddr = kDefaultIPAddress;
  136.     } else {
  137.         *ipAddr = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;
  138.     }
  139. }
  140.  
  141. static void IPAddressToString(InetHost ipAddr, char *outputString)
  142.     // Convert an IP address to a string suitable for printing.
  143. {
  144.     sprintf(outputString, "%d.%d.%d.%d", 
  145.         (ipAddr >> 24) & 0x0ff,
  146.         (ipAddr >> 16) & 0x0ff,
  147.         (ipAddr >> 8)  & 0x0ff,
  148.         (ipAddr >> 0)  & 0x0ff
  149.         );
  150. }
  151.  
  152. static void GetFlag(char *flagName, UInt32 flagValue, UInt32 *flags)
  153.     // Prompt the user for a flag.  The flagName is the user-visible
  154.     // name of the flag.  If the user types anything other than
  155.     // return or "n", flagVlaue is ORed into the flags variable.
  156. {
  157.     char tmpStr[256];
  158.     
  159.     printf("%s? (y/n)\n", flagName);
  160.     gets(tmpStr);
  161.     if ( tmpStr[0] != 0 && tmpStr[0] != 'n' && tmpStr[0] != 'N') {
  162.         (*flags) |= flagValue;
  163.     }
  164. }
  165.  
  166. static void PrintFlag(char *flagName, UInt32 flagMask, UInt32 flags)
  167.     // Print a flag.
  168. {
  169.     if ( (flags & flagMask) != 0 ) {
  170.         printf("%s ", flagName);
  171.     }
  172. }
  173.  
  174. ///////////////////////////////////////////////////////////////////
  175.  
  176. static OSStatus DoARPGetCacheReport(void)
  177.     // Call through to the equivalent ARPerations routine
  178.     // and then print the results.
  179. {
  180.     OSStatus err;
  181.     Handle cacheReportHandle;
  182.     char zero;
  183.     
  184.     printf("DoARPGetCacheReport\n");
  185.     cacheReportHandle = NewHandle(0);
  186.     err = MemError();
  187.     if (err == noErr) {
  188.         err = ARPGetCacheReport(cacheReportHandle);
  189.         if (err == noErr) {
  190.             zero = 0;
  191.             err = PtrAndHand(&zero, cacheReportHandle, sizeof(zero));
  192.             if (err == noErr) {
  193.                 HLock(cacheReportHandle);
  194.                 printf("%s\n\n", *cacheReportHandle);
  195.             }
  196.         }
  197.         DisposeHandle(cacheReportHandle);
  198.     }
  199.     printf("\n");
  200.     return (err);
  201. }
  202.  
  203. ///////////////////////////////////////////////////////////////////
  204.  
  205. static OSStatus DoARPAddEntry(void)
  206.     // Prompt user for input and then call straight through
  207.     // to the equivalent ARPerations routine.
  208. {
  209.     OSStatus err;
  210.     char interfaceName[256];
  211.     InetHost ipAddr;
  212.     InetHost ipMask = 0xFFFFFFFF;
  213.     HardwareAddress hwAddr;
  214.     char ipAddrString[256];
  215.     char hwAddrString[256];
  216.     UInt32 flags;
  217.     
  218.     printf("DoARPAddEntry\n");
  219.     GetInterfaceName(interfaceName);
  220.     GetIPAddress(&ipAddr);
  221.     IPAddressToString(ipAddr, ipAddrString);
  222.     GetHardwareAddress(&hwAddr);
  223.     HardwareAddressToString(hwAddr, hwAddrString);
  224.     flags = 0;
  225.     GetFlag("PERM   ", ACE_F_PERMANENT, &flags);
  226.     GetFlag("PUBLISH", ACE_F_PUBLISH, &flags);
  227.     GetFlag("MAPPING", ACE_F_MAPPING, &flags);
  228.     
  229.     printf("Adding ARP cache entry for %s -> %s on “%s”.\n", ipAddrString, hwAddrString, interfaceName);
  230.     
  231.     err = ARPAddEntry(interfaceName, IP_ARP_PROTO_TYPE, flags, 
  232.                         &ipAddr, sizeof(InetHost), &ipMask, &hwAddr, sizeof(hwAddr));
  233.  
  234.     return (err);
  235. }
  236.  
  237. ///////////////////////////////////////////////////////////////////
  238.  
  239. static OSStatus DoARPDeleteEntry(void)
  240.     // Prompt user for input and then call straight through
  241.     // to the equivalent ARPerations routine.
  242. {
  243.     OSStatus err;
  244.     InetHost ipAddr;
  245.     char interfaceName[256];
  246.     char ipAddrString[256];
  247.     
  248.     printf("DoARPDeleteEntry\n");
  249.     GetInterfaceName(interfaceName);
  250.     GetIPAddress(&ipAddr);
  251.     IPAddressToString(ipAddr, ipAddrString);
  252.     
  253.     printf("Deleting ARP cache entry for %s on “%s”.\n", ipAddrString, interfaceName);
  254.     
  255.     err = ARPDeleteEntry(interfaceName, IP_ARP_PROTO_TYPE, &ipAddr, sizeof(InetHost));
  256.  
  257.     return (err);
  258. }
  259.  
  260. ///////////////////////////////////////////////////////////////////
  261.  
  262. static OSStatus DoARPCacheQuery(void)
  263.     // Prompt user for input, call through to the equivalent
  264.     // ARPerations routine, and then print the results.
  265. {
  266.     OSStatus err;
  267.     char interfaceName[256];
  268.     InetHost ipAddr;
  269.     HardwareAddress hwAddr;
  270.     char ipAddrString[256];
  271.     char hwAddrString[256];
  272.     UInt32 flags;
  273.     
  274.     printf("DoARPCacheQuery\n");
  275.     GetInterfaceName(interfaceName);
  276.     GetIPAddress(&ipAddr);
  277.     IPAddressToString(ipAddr, ipAddrString);
  278.     
  279.     printf("Lookup ARP cache entry for %s on “%s”.\n", ipAddrString, interfaceName);
  280.     
  281.     err = ARPCacheQuery(interfaceName,
  282.                         IP_ARP_PROTO_TYPE,
  283.                         &ipAddr, sizeof(InetHost),
  284.                         &hwAddr, sizeof(hwAddr), &flags);
  285.  
  286.     if (err == noErr) {
  287.         HardwareAddressToString(hwAddr, hwAddrString);
  288.         printf("Hardware address is %s.\n", hwAddrString);
  289.         printf("Flags are ");
  290.         PrintFlag("PERM", ACE_F_PERMANENT, flags);
  291.         PrintFlag("PUBLISH", ACE_F_PUBLISH, flags);
  292.         PrintFlag("DYING", ACE_F_DYING, flags);
  293.         PrintFlag("RESOLVED", ACE_F_RESOLVED, flags);
  294.         PrintFlag("MAPPING", ACE_F_MAPPING, flags);
  295.         printf("\n");
  296.     }
  297.  
  298.     return (err);
  299. }
  300.  
  301. ///////////////////////////////////////////////////////////////////
  302.  
  303. // This sample uses a big global array (gInterfacesWeBroughtUp) to store
  304. // the list of interfaces that we have brought up.   The top of this
  305. // array is defined by gMaxInterfaceIndex.  The array stores
  306. // the configuration string used to create the interface (so that
  307. // we can display it to the user) and the interfaceCookie returned
  308. // by ARPInterfaceUp (so we can pass it back to ARPInterfaceDown
  309. // to tear down the interface).
  310.  
  311. enum {
  312.     kNumberOfOurARPInterfaces = 10            // Obviously an arbitrary limit.
  313. };
  314.  
  315. struct InterfaceInfo {
  316.     UInt32 cookie;
  317.     char configString[256];
  318. };
  319. typedef struct InterfaceInfo InterfaceInfo;
  320.  
  321. static InterfaceInfo gInterfacesWeBroughtUp[kNumberOfOurARPInterfaces];
  322.  
  323. static SInt32 gMaxInterfaceIndex = -1;
  324.  
  325. static OSStatus DoARPPrintOurInterfaces(void)
  326.     // Print the list of ARP interfaces we have brought up.
  327. {
  328.     SInt32 interfaceIndex;
  329.     
  330.     printf("DoARPPrintOurInterfaces\n");
  331.     printf("Interfaces we brought up:\n");
  332.     for (interfaceIndex = 0; interfaceIndex <= gMaxInterfaceIndex; interfaceIndex++) {
  333.         printf("%2d -- %s\n",
  334.             interfaceIndex,
  335.             gInterfacesWeBroughtUp[interfaceIndex].configString
  336.             );
  337.     }
  338.     printf("\n");
  339.     return (noErr);
  340. }
  341.  
  342. static OSStatus DoARPInterfaceUp(void)
  343.     // Prompt user for input and then call through to ARPInterfaceUp
  344.     // to bring up the interface.  If this succeeds, record the
  345.     // interface in gInterfacesWeBroughtUp so we can tear it down
  346.     // again.
  347. {
  348.     OSStatus err;
  349.     
  350.     printf("DoARPInterfaceUp\n");
  351.     err = noErr;
  352.     if ( gMaxInterfaceIndex == (kNumberOfOurARPInterfaces - 1) ) {
  353.         err = -3;
  354.     }
  355.     if (err == noErr) {
  356.         printf("Enter the configuration string of the interface you want to bring up:\n");
  357.         gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString[0] = 0;
  358.         gets(gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString);
  359.         if ( gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString[0] == 0 ) {
  360.             OTStrCopy(gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString, kDefaultInterfaceConfig);
  361.         }
  362.     }
  363.     if (err == noErr) {
  364.         err = ARPInterfaceUp(gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString,
  365.                         &gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].cookie); 
  366.     }
  367.     if (err == noErr) {
  368.         gMaxInterfaceIndex += 1;
  369.     }
  370.     
  371.     return (err);
  372. }
  373.  
  374. static OSStatus DoARPInterfaceDown(void)
  375.     // Prompt user for the numeric index of the interface they 
  376.     // want to tear down, and then call through to ARPInterfaceDown
  377.     // to tear it down.  Afterwards, delete the torn down element from
  378.     // the gInterfacesWeBroughtUp array
  379. {
  380.     OSStatus err;
  381.     SInt32 interfaceIndex;
  382.     char tmpStr[256];
  383.     
  384.     printf("DoARPInterfaceDown\n");
  385.     (void) DoARPPrintOurInterfaces();
  386.     printf("Enter an interface to take down:\n");
  387.     tmpStr[0] = 0;
  388.     gets(tmpStr);
  389.     err = noErr;
  390.     if ( sscanf(tmpStr, "%ld", &interfaceIndex) != 1 ) {
  391.         err = -1;
  392.     }
  393.     if (err == noErr) {
  394.         if ( (interfaceIndex < 0) || (interfaceIndex > gMaxInterfaceIndex) ) {
  395.             err = -2;
  396.         }
  397.     }
  398.     if (err == noErr) {
  399.         err = ARPInterfaceDown(gInterfacesWeBroughtUp[interfaceIndex].cookie);
  400.     }
  401.     if (err == noErr) {
  402.         gInterfacesWeBroughtUp[interfaceIndex] = gInterfacesWeBroughtUp[gMaxInterfaceIndex];
  403.         gMaxInterfaceIndex -= 1;
  404.     }
  405.     
  406.     return (err);
  407. }
  408.  
  409. ///////////////////////////////////////////////////////////////////
  410.  
  411. static OSStatus DoPrintCommandHelp(void)
  412.     // Print the current list of commands.
  413. {
  414.     printf("DoPrintCommandHelp\n");
  415.     printf("?) Prints this help.\n");
  416.     printf("\n");
  417.     printf("p) Print contents of ARP cache.\n");
  418.     printf("a) Add an ARP cache entry.\n");
  419.     printf("k) Delete an ARP cache entry.\n");
  420.     printf("l) Lookup an ARP cache entry.\n");
  421.     printf("\n");
  422.     printf("i) See the ARP interfaces we have brought up.\n");
  423.     printf("u) Bring up a new ARP interface.\n");
  424.     printf("d) Tear down an ARP interface.\n");
  425.     printf("\n");
  426.     printf("q) Quit.\n");
  427.     
  428.     return (noErr);
  429. }
  430.  
  431. ///////////////////////////////////////////////////////////////////
  432.  
  433. void main(void)
  434. {
  435.     OSStatus err;
  436.     char commandStr[256];
  437.     Boolean quitNow;
  438.         
  439.     printf("ARPSample -- A poor man's ARPing tool.\n");
  440.     
  441.     err = InitOpenTransport();
  442.     
  443.     if (err == noErr) {
  444.  
  445.         quitNow = false;
  446.         (void) DoPrintCommandHelp();
  447.         
  448.         // Welcome to the command loop.  Get a string from the user
  449.         // and use the first letter to dispatch to the relevant
  450.         // subroutine.
  451.         
  452.         do {
  453.             printf("Enter a letter corresponding to a command.\n");
  454.  
  455.             err = noErr;
  456.             gets(commandStr);
  457.             switch (commandStr[0]) {
  458.                 case '?':
  459.                     err = DoPrintCommandHelp();
  460.                     break;
  461.                 case 'p':
  462.                     err = DoARPGetCacheReport();
  463.                     break;
  464.                 case 'a':
  465.                     err = DoARPAddEntry();
  466.                     break;
  467.                 case 'k':
  468.                     err = DoARPDeleteEntry();
  469.                     break;
  470.                 case 'l':
  471.                     err = DoARPCacheQuery();
  472.                     break;
  473.                 case 'i':
  474.                     err = DoARPPrintOurInterfaces();
  475.                     break;
  476.                 case 'u':
  477.                     err = DoARPInterfaceUp();
  478.                     break;
  479.                 case 'd':
  480.                     err = DoARPInterfaceDown();
  481.                     break;
  482.                 case 'q':
  483.                     quitNow = true;
  484.                     break;
  485.                 case '\n':
  486.                     break;
  487.                 default:
  488.                     printf("Huh? “%s”\n", commandStr);
  489.                     break;
  490.             }
  491.             if (err != noErr) {
  492.                 printf("Error %ld.\n", err);
  493.             }
  494.         } while ( ! quitNow );    
  495.  
  496.         CloseOpenTransport();
  497.     }
  498.     
  499.     if (err == noErr) {
  500.         printf("Success.\n");
  501.     } else {
  502.         printf("Failed with error %d.\n", err);
  503.     }
  504.     printf("Done.  Press command-Q to Quit.\n");
  505. }
  506.  
  507.